package social.hub.oauth.jersey;

import java.util.Map;

import social.hub.oauth.OAuthServiceConfig;
import social.hub.oauth.OAuthServiceProvider;
import social.hub.oauth.OAuthToken;
import social.hub.util.UrlBuilder;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.filter.LoggingFilter;
import com.sun.jersey.api.representation.Form;
import com.sun.jersey.oauth.client.OAuthClientFilter;
import com.sun.jersey.oauth.signature.OAuthParameters;
import com.sun.jersey.oauth.signature.OAuthSecrets;

public class JerseyServiceProvider implements OAuthServiceProvider {

	private final Client client;
	private final OAuthServiceConfig config;

	public JerseyServiceProvider(OAuthServiceConfig serviceConfig) {

		this.config = serviceConfig;

		client = Client.create();
		client.addFilter(new LoggingFilter());

	}

	@Override
	public OAuthToken getAccessToken(OAuthToken authorizationToken, Map<String, String> parans) {

		OAuthParameters oauthParameters = createParameters();
		oauthParameters.setToken(authorizationToken.getToken());
		oauthParameters.setVerifier(parans.get(OAuthParameters.VERIFIER));

		OAuthSecrets oauthSecrets = createSecrets();
		oauthSecrets.setTokenSecret(authorizationToken.getSecret());

		return getToken(config.getAccessTokenUrl(), oauthParameters, oauthSecrets);

	}

	@Override
	public String getAuthorizationUrl(OAuthToken requestToken) {

		try {

			UrlBuilder builder = new UrlBuilder(config.getAuthorizeUrl());

			if (requestToken != null) {
				builder.addUrlParan("requestToken", requestToken.getToken());
				builder.addUrlParan("requestSecret", requestToken.getSecret());
			}

			return builder.toString();

		} catch (Exception e) {
			throw new RuntimeException("Erro getting authentication URL.", e);
		}

	}

	@Override
	public OAuthToken getRequestToken() {

		OAuthParameters oauthParameters = createParameters();
		OAuthSecrets oauthSecrets = createSecrets();

		return getToken(config.getRequestTokenUrl(), oauthParameters, oauthSecrets);

	}

	@Override
	public OAuthServiceConfig getServiceConfig() {
		return config;
	}

	private OAuthClientFilter createFilter(OAuthParameters oauthParameters, OAuthSecrets oauthSecrets) {
		return new OAuthClientFilter(client.getProviders(), oauthParameters, oauthSecrets, null, null, null, null);
	}

	private OAuthParameters createParameters() {

		OAuthParameters result = new OAuthParameters().consumerKey(config.getApiKey());

		if (config.getScope() != null) {
			result.put("scope", config.getScope());
		}

		if (config.getCallbackUrl() != null) {
			result.callback(config.getCallbackUrl());
		}

		return result;

	}

	private OAuthSecrets createSecrets() {
		return new OAuthSecrets().consumerSecret(config.getApiSecret());
	}

	private OAuthToken getToken(String url, OAuthParameters oauthParameters, OAuthSecrets oauthSecrets) {

		OAuthClientFilter oauthFilter = createFilter(oauthParameters, oauthSecrets);

		WebResource resource = client.resource(url);
		resource.addFilter(oauthFilter);
		Form response = resource.post(Form.class, " ");

		String token = response.getFirst(OAuthParameters.TOKEN);
		String secret = response.getFirst(OAuthParameters.TOKEN_SECRET);

		OAuthToken result = null;

		if (token != null) {
			result = new OAuthToken(token, secret);
		}

		return result;

	}

}
